package com.lexue.articlesync.adapter.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lexue.articlesync.adapter.AbstractPlatformAdapter;
import com.lexue.articlesync.entity.Article;
import com.lexue.articlesync.entity.Video;
import com.lexue.articlesync.entity.PlatformAuth;
import com.lexue.articlesync.service.ImageHostingService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 头条号平台适配器
 */
@Slf4j
@Component
public class ToutiaoAdapter extends AbstractPlatformAdapter {
    
    @Autowired
    private ImageHostingService imageHostingService;
    
    private static final String PLATFORM_CODE = "toutiao";
    private static final String PLATFORM_NAME = "头条号";
    
    // 头条号API端点
    private static final String API_BASE_URL = "https://mp.toutiao.com";
    // 根据网页插件的真实API更新端点
    private static final String USER_INFO_URL = API_BASE_URL + "/mp/agw/media/get_media_info";
    private static final String ARTICLE_PUBLISH_URL = API_BASE_URL + "/mp/agw/article/publish?source=mp&type=article";
    // 更新为新的图片上传接口
    private static final String IMAGE_UPLOAD_URL = API_BASE_URL + "/spice/image?upload_source=20020003&aid=1231&device_platform=web&need_cover_url=1";
    private static final String PROFILE_PAGE_URL = API_BASE_URL + "/profile_v3/graphic/publish";
    
    public ToutiaoAdapter() {
        super();
        // 重新配置HTTP客户端，确保正确处理压缩响应
        this.httpClient = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                // 添加拦截器来处理响应编码问题
                .addInterceptor(chain -> {
                    Request originalRequest = chain.request();
                    
                    // 对于头条号API，不主动请求压缩，让服务器决定
                    Request.Builder requestBuilder = originalRequest.newBuilder();
                    
                    // 如果请求头中有Accept-Encoding，移除它
                    requestBuilder.removeHeader("Accept-Encoding");
                    
                    Request newRequest = requestBuilder.build();
                    Response response = chain.proceed(newRequest);
                    
                    log.debug("头条号HTTP请求: {} {} - 响应状态: {} - Content-Type: {} - Content-Encoding: {}", 
                             newRequest.method(), newRequest.url(), response.code(),
                             response.header("Content-Type"), response.header("Content-Encoding"));
                    
                    return response;
                })
                .build();
    }
    
    @Override
    public String getPlatformCode() {
        return PLATFORM_CODE;
    }
    
    @Override
    public String getPlatformName() {
        return PLATFORM_NAME;
    }
    
    @Override
    public String[] getSupportedContentTypes() {
        return new String[]{"article", "video"};
    }
    
    @Override
    public boolean validateAuth(PlatformAuth auth) {
        if (!super.validateAuth(auth)) {
            return false;
        }
        
        // 对于头条平台，优先检查cookies
        if (auth.getCookies() != null && !auth.getCookies().trim().isEmpty()) {
            return validateCookiesAuth(auth);
        }
        
        // 如果没有cookies，尝试传统的token验证
        if (auth.getAccessToken() != null && !auth.getAccessToken().trim().isEmpty()) {
            return validateTokenAuth(auth);
        }
        
        return false;
    }
    
    /**
     * 验证cookies认证
     */
    private boolean validateCookiesAuth(PlatformAuth auth) {
        try {
            // 使用真实的头条号用户信息API
            Request request = createRequestBuilder()
                    .url(USER_INFO_URL)
                    .addHeader("Cookie", auth.getCookies())
                    .addHeader("Referer", "https://mp.toutiao.com/")
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .addHeader("X-Requested-With", "XMLHttpRequest")
                    .build();
            
            try (Response response = executeRequest(request)) {
                if (response.isSuccessful()) {
                    String responseBody = response.body().string();
                    log.debug("头条号用户信息响应: {}", responseBody);
                    
                    JSONObject jsonResponse = JSON.parseObject(responseBody);
                    
                    // 检查返回的数据结构
                    if (jsonResponse != null && jsonResponse.containsKey("data")) {
                        JSONObject data = jsonResponse.getJSONObject("data");
                        if (data != null && data.containsKey("user")) {
                            JSONObject user = data.getJSONObject("user");
                            // 检查是否有用户ID，表示登录成功
                            if (user != null && user.containsKey("id")) {
                                log.info("头条号cookies验证成功，用户ID: {}", user.getString("id"));
                                return true;
                            }
                        }
                    }
                    
                    log.warn("头条号cookies验证失败，返回数据格式不正确: {}", responseBody);
                } else {
                    log.warn("头条号cookies验证失败，HTTP状态码: {}", response.code());
                }
            }
        } catch (Exception e) {
            log.error("验证头条号cookies失败", e);
        }
        return false;
    }
    
    /**
     * 验证token认证
     */
    private boolean validateTokenAuth(PlatformAuth auth) {
        try {
            // 使用用户信息API进行token验证
            Request request = createRequestBuilder()
                    .url(USER_INFO_URL)
                    .addHeader("Authorization", "Bearer " + auth.getAccessToken())
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .build();
            
            try (Response response = executeRequest(request)) {
                if (response.isSuccessful()) {
                    String responseBody = response.body().string();
                    JSONObject jsonResponse = JSON.parseObject(responseBody);
                    
                    // 检查返回的数据结构
                    if (jsonResponse != null && jsonResponse.containsKey("data")) {
                        JSONObject data = jsonResponse.getJSONObject("data");
                        if (data != null && data.containsKey("user")) {
                            return true;
                        }
                    }
                }
                return false;
            }
        } catch (Exception e) {
            log.error("验证头条号token失败", e);
            return false;
        }
    }
    
    @Override
    public PublishResult publishArticle(Article article, PlatformAuth auth, PublishOptions options) {
        validateRequired(article.getTitle(), "文章标题");
        validateRequired(article.getContent(), "文章内容");
        
        try {
            // 第一步：访问发布页面获取必要的session信息
            log.info("开始访问头条号发布页面: {}", PROFILE_PAGE_URL);
            Request profileRequest = new Request.Builder()
                    .url(PROFILE_PAGE_URL)
                    .addHeader("Cookie", auth.getCookies())
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
                    .addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                    .build();
            
            try (Response profileResponse = executeRequest(profileRequest)) {
                String profileBody = profileResponse.body().string();
                log.debug("访问发布页面状态: {}", profileResponse.code());
                
                if (!profileResponse.isSuccessful()) {
                    String errorDetail = analyzeHttpError(profileResponse.code(), profileBody);
                    log.warn("无法访问头条号发布页面: {}", errorDetail);
                    return buildFailureResult("无法访问头条号发布页面: " + errorDetail);
                }
                
                // 检查是否需要登录
                if (profileBody.contains("用户登录") || profileBody.contains("login")) {
                    return buildFailureResult("用户未登录，请重新获取有效的cookies");
                }
                
                log.info("成功访问头条号发布页面，准备发布文章");
            }
            
            // 第二步：准备发布数据
            String title = options.getTitle() != null ? options.getTitle() : article.getTitle();
            String content = options.getContent() != null ? options.getContent() : 
                           (article.getHtmlContent() != null ? article.getHtmlContent() : article.getContent());
            
            log.info("准备发布文章: 标题={}, 内容长度={}", title, content.length());
            
            // 构建表单数据（根据头条号真实发布流程）
            FormBody.Builder formBuilder = new FormBody.Builder()
                    .add("title", limitLength(title, 100))
                    .add("content", content)
                    .add("article_ad_type", "2")          // 广告类型
                    .add("article_type", "0")            // 文章类型：0=图文
                    .add("source", "0")                  // 来源
                    .add("pgc_id", "7543294117435769398") // 内容创作者ID
                    .add("save", "1")                   // 保存并发布（1=立即发布，0=仅保存草稿）
                    .add("timer_status", "0")           // 定时状态
                    .add("is_refute_rumor", "0")        // 是否辟谣
                    .add("search_creation_info", "{\"searchTopOne\":0,\"abstract\":\"\",\"clue_id\":\"\"}") // 搜索创作信息
                    .add("title_id", "")                // 标题ID
                    .add("ic_uri_list", "")             // 图标URI列表
                    .add("appid_list", "")              // 应用ID列表
                    .add("stock_ids", "")               // 股票ID
                    .add("concern_list", "")            // 关注列表
                    .add("mp_editor_stat", "{}")        // 编辑器状态
                    .add("educluecard", "")             // 教育线索卡
                    .add("is_fans_article", "0")       // 是否粉丝文章
                    .add("govern_forward", "0")         // 治理转发
                    .add("praise", "0")                 // 点赞
                    .add("disable_praise", "0")         // 禁止点赞
                    .add("tree_plan_article", "0")      // 树状计划文章
                    .add("star_order_id", "")           // 明星订单ID
                    .add("star_order_name", "")         // 明星订单名称
                    .add("activity_tag", "0")           // 活动标签
                    .add("trends_writing_tag", "0")     // 趋势写作标签
                    .add("claim_exclusive", "0");       // 独家声明
            
            // 处理封面图片 - 支持新的pgc_feed_covers格式
            List<JSONObject> coverImageList = new ArrayList<>();
            JSONObject draftFormData = new JSONObject();
            
            if (options.getCoverImage() != null && !options.getCoverImage().trim().isEmpty()) {
                try {
                    log.info("检测到封面图片，开始处理: {}", options.getCoverImage());
                    
                    // 判断是本地文件还是网络URL
                    String imageUrl = options.getCoverImage();
                    if (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://")) {
                        // 本地文件路径，需要先检查文件是否存在
                        java.io.File localFile = new java.io.File(imageUrl);
                        if (!localFile.exists()) {
                            log.warn("本地封面图片文件不存在: {}", imageUrl);
                            // 尝试添加项目路径前缀
                            String projectPath = System.getProperty("user.dir");
                            imageUrl = projectPath + "/" + imageUrl;
                            localFile = new java.io.File(imageUrl);
                            if (!localFile.exists()) {
                                log.error("找不到封面图片文件: {}", imageUrl);
                                // 封面图片文件不存在时，保存为草稿而不是直接发布
                                return saveAsDraft(article, auth, options, "找不到封面图片文件: " + imageUrl);
                            } else {
                                // 找到了文件，更新imageUrl
                                imageUrl = localFile.getAbsolutePath();
                            }
                        }
                    }
                    
                    // 如果图片文件存在，继续上传处理
                    if (new java.io.File(imageUrl).exists() || imageUrl.startsWith("http")) {
                        // 上传封面图片并获取有效的URI
                        JSONObject uploadedImageInfo = uploadImageForCover(imageUrl, auth);
                        if (uploadedImageInfo != null) {
                            coverImageList.add(uploadedImageInfo);
                            log.info("封面图片上传成功，图片信息: {}", uploadedImageInfo.toJSONString());
                            
                            // 设置 draft_form_data
                            draftFormData.put("coverType", 3); // 3表示自定义封面
                        } else {
                            log.warn("封面图片上传失败，文章将保存为草稿状态");
                            // 封面图片上传失败时，保存为草稿而不是直接发布
                            return saveAsDraft(article, auth, options, "封面图片上传失败");
                        }
                    } else {
                        log.warn("封面图片文件不存在，文章将保存为草稿状态: {}", imageUrl);
                        // 封面图片文件不存在时，保存为草稿而不是直接发布
                        return saveAsDraft(article, auth, options, "封面图片文件不存在");
                    }
                } catch (Exception e) {
                    log.error("封面图片上传异常，文章将保存为草稿状态: {}", e.getMessage(), e);
                    // 封面图片上传异常时，保存为草稿而不是直接发布
                    return saveAsDraft(article, auth, options, "封面图片处理异常: " + e.getMessage());
                }
            } else {
                log.info("未设置封面图片，将发布纯文字文章");
                draftFormData.put("coverType", 0); // 0表示无封面
            }
            
            // 添加封面相关字段
            formBuilder.add("pgc_feed_covers", JSON.toJSONString(coverImageList));
            formBuilder.add("draft_form_data", draftFormData.toJSONString());
            
            // 记录最终的封面图片数据
            log.info("最终封面图片数据: {}", JSON.toJSONString(coverImageList));
            log.info("草稿表单数据: {}", draftFormData.toJSONString());
            
            RequestBody formBody = formBuilder.build();
            
            // 第三步：发送发布请求
            log.info("开始发送头条号发布请求: {}", ARTICLE_PUBLISH_URL);
            Request publishRequest = new Request.Builder()
                    .url(ARTICLE_PUBLISH_URL)
                    .post(formBody)
                    .addHeader("Cookie", auth.getCookies())
                    .addHeader("Referer", PROFILE_PAGE_URL)
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .addHeader("X-Requested-With", "XMLHttpRequest")
                    .addHeader("Accept", "application/json, text/javascript, */*; q=0.01")
                    .addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                    // 移除 Accept-Encoding 头，避免压缩导致的解析问题
                    .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                    .addHeader("Origin", "https://mp.toutiao.com")
                    .addHeader("Sec-Fetch-Dest", "empty")
                    .addHeader("Sec-Fetch-Mode", "cors")
                    .addHeader("Sec-Fetch-Site", "same-origin")
                    .build();
            
            try (Response response = executeRequest(publishRequest)) {
                String responseBody = null;
                try {
                    responseBody = response.body().string();
                    
                    // 检查响应是否为有效文本（防止二进制数据）
                    if (responseBody.length() > 0) {
                        // 检查是否包含异常字符或乱码
                        boolean containsBinaryData = false;
                        for (int i = 0; i < Math.min(responseBody.length(), 100); i++) {
                            char c = responseBody.charAt(i);
                            // 检查是否包含控制字符或非打印字符
                            if (c < 32 && c != '\n' && c != '\r' && c != '\t') {
                                containsBinaryData = true;
                                break;
                            }
                        }
                        
                        if (containsBinaryData) {
                            log.warn("头条号返回了二进制数据或压缩数据，可能是响应编码问题");
                            return buildFailureResult("头条号发布响应格式异常，可能是服务器返回了压缩数据。请检查网络连接或稍后重试。");
                        }
                    }
                    
                    log.info("头条号发布响应: HTTP {} - 响应长度: {} - 内容预览: {}", 
                             response.code(), responseBody.length(), 
                             responseBody.length() > 200 ? responseBody.substring(0, 200) + "..." : responseBody);
                } catch (Exception e) {
                    log.error("读取头条号响应内容失败: {}", e.getMessage());
                    return buildFailureResult("读取头条号响应失败: " + e.getMessage());
                }
                
                // 优先检查响应体中是否包含"失败"关键词
                if (responseBody != null && (responseBody.contains("失败") || responseBody.contains("非法"))) {
                    log.warn("头条号发布失败，响应包含失败关键词: {}", responseBody);
                    return buildFailureResult("头条号发布失败: " + extractErrorMessage(responseBody));
                }
                
                if (response.isSuccessful()) {
                    try {
                        JSONObject jsonResponse = JSON.parseObject(responseBody);
                        
                        // 检查响应状态
                        if (jsonResponse != null) {
                            // 检查是否有错误码或状态
                            if (jsonResponse.containsKey("err_no") && jsonResponse.getInteger("err_no") != 0) {
                                String errorMsg = jsonResponse.getString("err_tips");
                                if (errorMsg == null || errorMsg.isEmpty()) {
                                    errorMsg = jsonResponse.getString("message");
                                }
                                
                                // 特别处理图片URI错误
                                if (jsonResponse.getInteger("err_no") == 7115 || 
                                    (errorMsg != null && errorMsg.contains("图片uri非法"))) {
                                    log.error("头条号图片URI错误: {}", errorMsg);
                                    // 图片相关错误时，保存为草稿而不是直接发布失败
                                    return saveAsDraft(article, auth, options, "图片上传或处理失败: " + errorMsg);
                                }
                                
                                return buildFailureResult("头条号发布失败: " + (errorMsg != null ? errorMsg : "未知错误"));
                            }
                            
                            // 检查是否发布成功 - 头条号成功发布后会返回具体的文章信息
                            if (jsonResponse.containsKey("data")) {
                                JSONObject data = jsonResponse.getJSONObject("data");
                                if (data != null) {
                                    // 方式1：检查是否有文章ID
                                    if (data.containsKey("pgc_id")) {
                                        String contentId = data.getString("pgc_id");
                                        if (contentId != null && !contentId.equals("0")) {
                                            // 额外验证文章是否真的发布
                                            boolean verified = verifyArticlePublished(contentId, auth);
                                            if (verified) {
                                                String contentUrl = "https://mp.toutiao.com/profile_v3/graphic/articles?pgc_id=" + contentId;
                                                log.info("头条号文章发布成功并验证通过: ID={}", contentId);
                                                return buildSuccessResult(contentId, contentUrl);
                                            } else {
                                                log.warn("头条号API返回成功但验证发现文章未真正发布: ID={}", contentId);
                                                return buildFailureResult("发布失败：文章未真正发布，可能被保存为草稿或需要人工审核");
                                            }
                                        }
                                    }
                                    
                                    // 方式2：检查是否有文章URL
                                    if (data.containsKey("share_url")) {
                                        String shareUrl = data.getString("share_url");
                                        if (shareUrl != null && !shareUrl.isEmpty()) {
                                            log.info("头条号文章发布成功: URL={}", shareUrl);
                                            return buildSuccessResult("published", shareUrl);
                                        }
                                    }
                                    
                                    // 方式3：检查是否有状态字段
                                    if (data.containsKey("status")) {
                                        String status = data.getString("status");
                                        if ("success".equals(status) || "published".equals(status)) {
                                            log.info("头条号文章发布成功: 状态={}", status);
                                            return buildSuccessResult("published", PROFILE_PAGE_URL);
                                        }
                                    }
                                }
                            }
                            
                            // 检查是否有success字段
                            if (jsonResponse.containsKey("success") && jsonResponse.getBoolean("success")) {
                                log.info("头条号文章发布成功");
                                return buildSuccessResult("published", PROFILE_PAGE_URL);
                            }
                            
                            // 检查是否有通用成功标识
                            if (jsonResponse.containsKey("code") && jsonResponse.getInteger("code") == 0) {
                                log.info("头条号文章发布成功");
                                return buildSuccessResult("published", PROFILE_PAGE_URL);
                            }
                            
                            // 检查是否有通用错误信息
                            if (jsonResponse.containsKey("message")) {
                                String errorMsg = jsonResponse.getString("message");
                                // 如果message不是错误信息，可能是发布成功
                                if (errorMsg != null && !errorMsg.contains("失败") && !errorMsg.contains("错误") && !errorMsg.contains("非法")) {
                                    log.info("头条号文章可能发布成功: {}", errorMsg);
                                    return buildSuccessResult("published", PROFILE_PAGE_URL);
                                }
                                return buildFailureResult("头条号发布失败: " + errorMsg);
                            }
                        }
                        
                        // JSON解析成功但没有预期数据
                        return buildFailureResult("头条号发布失败，返回数据格式不正确: " + responseBody);
                        
                    } catch (Exception e) {
                        // JSON解析失败，可能返回的是HTML或其他格式
                        log.warn("头条号响应JSON解析失败: {} - 响应内容前100字符: {}", 
                                e.getMessage(), 
                                responseBody != null && responseBody.length() > 100 ? 
                                    responseBody.substring(0, 100) : responseBody);
                        
                        // 检查是否是压缩数据导致的问题
                        if (responseBody != null && responseBody.length() > 0) {
                            // 如果包含大量非ASCII字符，可能是编码问题
                            long nonAsciiCount = responseBody.chars().filter(c -> c > 127).count();
                            if (nonAsciiCount > responseBody.length() * 0.5) {
                                return buildFailureResult("头条号发布响应格式异常: 服务器返回了编码异常的数据，可能是压缩或编码问题。请稍后重试。");
                            }
                        }
                        
                        return buildFailureResult("头条号发布失败，响应格式异常: " + extractErrorFromHtml(responseBody));
                    }
                } else {
                    // HTTP状态码不成功
                    String errorDetail = analyzeHttpError(response.code(), responseBody);
                    log.warn("头条号发布HTTP错误: {} - {}", response.code(), errorDetail);
                    return buildFailureResult(errorDetail);
                }
            }
            
        } catch (Exception e) {
            log.error("头条号文章发布异常", e);
            return buildFailureResult("头条号发布异常: " + e.getMessage());
        }
    }
    
    @Override
    public PublishResult publishVideo(Video video, PlatformAuth auth, PublishOptions options) {
        validateRequired(video.getTitle(), "视频标题");
        validateRequired(video.getFilePath(), "视频文件");
        
        try {
            // 头条号目前主要支持图文内容，视频发布功能暂未完全实现
            // 这里返回一个提示信息
            log.warn("头条号视频发布功能暂未完全实现，建议使用图文发布");
            return buildFailureResult("头条号平台暂不支持通过API直接发布视频，请手动上传");
            
        } catch (Exception e) {
            log.error("头条号视频发布异常", e);
            return buildFailureResult("头条号视频发布异常: " + e.getMessage());
        }
    }
    
    @Override
    public PublishStatus checkPublishStatus(String platformContentId, PlatformAuth auth) {
        try {
            // 头条号发布后可以通过草稿链接查看状态
            // 这里简化处理，实际可以通过模拟访问草稿页面来获取状态
            String checkUrl = PROFILE_PAGE_URL + "?pgc_id=" + platformContentId;
            
            Request request = new Request.Builder()
                    .url(checkUrl)
                    .addHeader("Cookie", auth.getCookies())
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .build();
            
            try (Response response = executeRequest(request)) {
                if (response.isSuccessful()) {
                    // 如果能成功访问草稿页面，说明文章存在
                    return PublishStatus.SUCCESS;
                } else if (response.code() == 404) {
                    return PublishStatus.FAILED;
                } else {
                    return PublishStatus.PROCESSING;
                }
            }
        } catch (Exception e) {
            log.error("检查头条号发布状态失败", e);
        }
        
        return PublishStatus.SUCCESS; // 默认返回成功
    }
    
    /**
     * 上传图片到头条号并返回有效的URI信息
     * @param imageUrl 图片URL（可以是网络图片或本地文件路径）
     * @param auth 认证信息
     * @return 返回头条号需要的图片信息格式，失败返回null
     */
    private String uploadImage(String imageUrl, PlatformAuth auth) {
        try {
            log.info("开始上传图片到头条号: {}", imageUrl);
            
            // 先将图片上传到可访问的位置（如果是本地文件）
            String accessibleImageUrl = prepareImageUrl(imageUrl);
            if (accessibleImageUrl == null) {
                log.error("无法准备图片URL: {}", imageUrl);
                return null;
            }
            
            log.info("图片URL准备完成: {}", accessibleImageUrl);
            
            // 使用新的spice/image接口，传递imageUrl参数
            RequestBody requestBody = new FormBody.Builder()
                    .add("imageUrl", accessibleImageUrl)
                    .build();
            
            Request uploadRequest = new Request.Builder()
                    .url(IMAGE_UPLOAD_URL)
                    .post(requestBody)
                    .addHeader("Cookie", auth.getCookies())
                    .addHeader("Referer", PROFILE_PAGE_URL)
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .addHeader("X-Requested-With", "XMLHttpRequest")
                    .addHeader("Accept", "application/json, text/javascript, */*; q=0.01")
                    .addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                    .addHeader("Content-Type", "application/x-www-form-urlencoded")
                    .addHeader("Origin", "https://mp.toutiao.com")
                    .addHeader("Sec-Fetch-Dest", "empty")
                    .addHeader("Sec-Fetch-Mode", "cors")
                    .addHeader("Sec-Fetch-Site", "same-origin")
                    .build();
            
            try (Response response = executeRequest(uploadRequest)) {
                String responseBody = response.body().string();
                log.info("图片上传响应: HTTP {} - {}", response.code(), responseBody);
                
                if (response.isSuccessful()) {
                    try {
                        JSONObject jsonResponse = JSON.parseObject(responseBody);
                        if (jsonResponse != null) {
                            // 检查是否有错误码
                            if (jsonResponse.containsKey("err_no") && jsonResponse.getInteger("err_no") != 0) {
                                String errorMsg = jsonResponse.getString("err_tips");
                                if (errorMsg == null || errorMsg.isEmpty()) {
                                    errorMsg = jsonResponse.getString("message");
                                }
                                log.error("图片上传失败: {}", errorMsg);
                                return null;
                            }
                            
                            // 检查数据字段
                            if (jsonResponse.containsKey("data")) {
                                JSONObject data = jsonResponse.getJSONObject("data");
                                if (data != null) {
                                    // 获取上传成功的图片信息
                                    String uri = data.getString("uri");
                                    String url = data.getString("url");
                                    String originUri = data.getString("origin_uri");
                                    String webUri = data.getString("web_uri");
                                    
                                    // 优先使用web_uri，其次使用url
                                    String finalUrl = webUri != null ? webUri : url;
                                    String finalUri = uri != null ? uri : originUri;
                                    
                                    if (finalUri != null && finalUrl != null) {
                                        // 构建头条号需要的格式
                                        String imageInfo = String.format(
                                            "{\"id\":0,\"url\":\"%s\",\"uri\":\"%s\",\"origin_uri\":\"%s\"}",
                                            finalUrl, finalUri, originUri != null ? originUri : finalUri
                                        );
                                        log.info("图片上传成功: uri={}, url={}", finalUri, finalUrl);
                                        return imageInfo;
                                    }
                                }
                            }
                            
                            // 检查是否有通用成功标识
                            if (jsonResponse.containsKey("code") && jsonResponse.getInteger("code") == 0) {
                                // 尝试从其他字段获取图片信息
                                String directUrl = jsonResponse.getString("url");
                                if (directUrl != null) {
                                    String imageInfo = String.format(
                                        "{\"id\":0,\"url\":\"%s\",\"uri\":\"%s\",\"origin_uri\":\"%s\"}",
                                        directUrl, directUrl, directUrl
                                    );
                                    log.info("图片上传成功（使用直接URL）: {}", directUrl);
                                    return imageInfo;
                                }
                            }
                            
                            // 检查是否有错误信息
                            if (jsonResponse.containsKey("message")) {
                                String errorMsg = jsonResponse.getString("message");
                                log.error("图片上传失败: {}", errorMsg);
                            }
                        }
                        
                    } catch (Exception e) {
                        log.error("解析图片上传响应失败: {}", e.getMessage());
                    }
                } else {
                    log.error("图片上传HTTP错误: {} - {}", response.code(), responseBody);
                }
            }
            
        } catch (Exception e) {
            log.error("图片上传异常", e);
        }
        
        return null;
    }
    
    /**
     * 专为封面图片上传设计的方法，返回完整的图片信息对象
     * @param imageUrl 图片URL（可以是网络图片或本地文件路径）
     * @param auth 认证信息
     * @return 返回符合头条号封面要求的完整图片信息对象，失败返回null
     */
    private JSONObject uploadImageForCover(String imageUrl, PlatformAuth auth) {
        try {
            log.info("开始上传封面图片到头条号: {}", imageUrl);
            
            // 先将图片上传到可访问的位置（如果是本地文件）
            String accessibleImageUrl = prepareImageUrl(imageUrl);
            if (accessibleImageUrl == null) {
                log.error("无法准备图片URL: {}", imageUrl);
                return null;
            }
            
            log.info("封面图片URL准备完成: {}", accessibleImageUrl);
            
            // 使用spice/image接口，传递imageUrl参数
            RequestBody requestBody = new FormBody.Builder()
                    .add("imageUrl", accessibleImageUrl)
                    .build();
            
            Request uploadRequest = new Request.Builder()
                    .url(IMAGE_UPLOAD_URL)
                    .post(requestBody)
                    .addHeader("Cookie", auth.getCookies())
                    .addHeader("Referer", PROFILE_PAGE_URL)
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .addHeader("X-Requested-With", "XMLHttpRequest")
                    .addHeader("Accept", "application/json, text/javascript, */*; q=0.01")
                    .addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                    .addHeader("Content-Type", "application/x-www-form-urlencoded")
                    .addHeader("Origin", "https://mp.toutiao.com")
                    .build();
            
            try (Response response = executeRequest(uploadRequest)) {
                String responseBody = response.body().string();
                log.info("封面图片上传响应: HTTP {} - {}", response.code(), responseBody);
                
                if (response.isSuccessful()) {
                    try {
                        JSONObject jsonResponse = JSON.parseObject(responseBody);
                        if (jsonResponse != null) {
                            // 检查是否有错误码
                            if (jsonResponse.containsKey("err_no") && jsonResponse.getInteger("err_no") != 0) {
                                String errorMsg = jsonResponse.getString("err_tips");
                                log.error("封面图片上传失败: {}", errorMsg);
                                return null;
                            }
                            
                            // 检查数据字段
                            if (jsonResponse.containsKey("data")) {
                                JSONObject data = jsonResponse.getJSONObject("data");
                                if (data != null) {
                                    // 构建符合pgc_feed_covers格式的图片信息
                                    JSONObject coverImageInfo = new JSONObject();
                                    coverImageInfo.put("id", "");
                                    coverImageInfo.put("url", data.getString("url"));
                                    coverImageInfo.put("uri", data.getString("uri"));
                                    coverImageInfo.put("ic_uri", "");
                                    coverImageInfo.put("thumb_width", 1280);
                                    coverImageInfo.put("thumb_height", 854);
                                    
                                    JSONObject extra = new JSONObject();
                                    extra.put("from_content_uri", "");
                                    extra.put("from_content", "0");
                                    coverImageInfo.put("extra", extra);
                                    
                                    log.info("封面图片上传成功: {}", coverImageInfo.toJSONString());
                                    return coverImageInfo;
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("解析封面图片上传响应失败: {}", e.getMessage());
                    }
                } else {
                    log.error("封面图片上传HTTP错误: {} - {}", response.code(), responseBody);
                }
            }
            
        } catch (Exception e) {
            log.error("封面图片上传异常", e);
        }
        
        return null;
    }
    
    /**
     * 准备图片URL，确保头条号能够访问
     */
    private String prepareImageUrl(String imageUrl) {
        try {
            // 如果是网络图片，直接使用
            if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
                return imageUrl;
            }
            
            // 如果是本地文件，使用图片托管服务
            java.io.File localFile = new java.io.File(imageUrl);
            if (!localFile.exists()) {
                // 尝试添加项目路径前缀
                String projectPath = System.getProperty("user.dir");
                String fullPath = projectPath + "/" + imageUrl;
                localFile = new java.io.File(fullPath);
                if (localFile.exists()) {
                    imageUrl = fullPath;
                } else {
                    log.error("本地图片文件不存在: {}", imageUrl);
                    return null;
                }
            }
            
            // 使用图片托管服务将本地图片上传到可访问位置
            String hostedUrl = imageHostingService.hostLocalImage(imageUrl);
            if (hostedUrl != null) {
                log.info("本地图片托管成功: {} -> {}", imageUrl, hostedUrl);
                return hostedUrl;
            } else {
                log.error("托管本地图片失败: {}", imageUrl);
                return null;
            }
            
        } catch (Exception e) {
            log.error("准备图片URL异常", e);
            return null;
        }
    }
    
    /**
     * 下载图片数据
     */
    private byte[] downloadImageData(String imageUrl) {
        try {
            if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
                // 网络图片，下载
                Request request = new Request.Builder()
                        .url(imageUrl)
                        .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                        .build();
                
                try (Response response = executeRequest(request)) {
                    if (response.isSuccessful()) {
                        return response.body().bytes();
                    }
                }
            } else {
                // 本地文件路径
                java.io.File file = new java.io.File(imageUrl);
                if (file.exists()) {
                    return java.nio.file.Files.readAllBytes(file.toPath());
                }
            }
        } catch (Exception e) {
            log.error("下载图片失败: {}", e.getMessage());
        }
        return null;
    }
    
    /**
     * 从 URL 中提取文件名
     */
    private String extractFileName(String imageUrl) {
        try {
            if (imageUrl.contains("/")) {
                String fileName = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
                // 如果文件名包含参数，去除参数
                if (fileName.contains("?")) {
                    fileName = fileName.substring(0, fileName.indexOf("?"));
                }
                // 如果没有扩展名，默认为 jpg
                if (!fileName.contains(".")) {
                    fileName += ".jpg";
                }
                return fileName;
            }
        } catch (Exception e) {
            log.warn("提取文件名失败: {}", e.getMessage());
        }
        return "image_" + System.currentTimeMillis() + ".jpg";
    }
    
    /**
     * 根据文件名获取内容类型
     */
    private String getImageContentType(String fileName) {
        String lowerName = fileName.toLowerCase();
        if (lowerName.endsWith(".png")) {
            return "image/png";
        } else if (lowerName.endsWith(".gif")) {
            return "image/gif";
        } else if (lowerName.endsWith(".webp")) {
            return "image/webp";
        } else {
            return "image/jpeg";  // 默认为 JPEG
        }
    }
    
    /**
     * 从响应体中提取错误信息
     */
    private String extractErrorMessage(String responseBody) {
        if (responseBody == null || responseBody.isEmpty()) {
            return "未知错误";
        }
        
        try {
            // 尝试解析JSON格式的错误信息
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            if (jsonResponse != null) {
                // 检查常见的错误字段
                if (jsonResponse.containsKey("err_tips")) {
                    return jsonResponse.getString("err_tips");
                }
                if (jsonResponse.containsKey("message")) {
                    return jsonResponse.getString("message");
                }
                if (jsonResponse.containsKey("error_message")) {
                    return jsonResponse.getString("error_message");
                }
            }
        } catch (Exception e) {
            // JSON解析失败，尝试从HTML中提取
            return extractErrorFromHtml(responseBody);
        }
        
        // 直接返回包含"失败"的部分内容
        int failIndex = responseBody.indexOf("失败");
        if (failIndex >= 0) {
            int start = Math.max(0, failIndex - 50);
            int end = Math.min(responseBody.length(), failIndex + 50);
            return responseBody.substring(start, end).trim();
        }
        
        return "发布失败，请检查内容格式和认证状态";
    }
    
    /**
     * 从HTML响应中提取错误信息
     */
    private String extractErrorFromHtml(String htmlContent) {
        if (htmlContent == null || htmlContent.isEmpty()) {
            return "响应内容为空";
        }
        
        // 检查是否包含登录相关内容
        if (htmlContent.contains("用户登录") || htmlContent.contains("login") || 
            htmlContent.contains("请登录") || htmlContent.contains("登录页面")) {
            return "用户未登录或登录已过期，请重新获取cookies";
        }
        
        // 检查是否包含权限相关内容
        if (htmlContent.contains("权限") || htmlContent.contains("unauthorized") || 
            htmlContent.contains("forbidden")) {
            return "权限不足，请检查账户状态";
        }
        
        // 检查是否包含验证码
        if (htmlContent.contains("验证码") || htmlContent.contains("captcha")) {
            return "需要验证码验证，请在浏览器中完成验证后重新获取cookies";
        }
        
        // 检查是否包含服务器错误
        if (htmlContent.contains("服务器错误") || htmlContent.contains("500") || 
            htmlContent.contains("Internal Server Error")) {
            return "头条服务器内部错误，请稍后重试";
        }
        
        return "服务器返回异常响应，请检查网络连接和认证状态";
    }
    
    /**
     * 分析HTTP错误状态码
     */
    private String analyzeHttpError(int statusCode, String responseBody) {
        switch (statusCode) {
            case 400:
                return "请求参数错误，请检查文章内容格式";
            case 401:
                return "认证失败，cookies已过期或无效，请重新获取";
            case 403:
                return "权限不足，账户可能被限制或需要完成额外验证";
            case 404:
                return "请求的接口不存在，可能是头条API已更新";
            case 429:
                return "请求过于频繁，请稍后重试";
            case 500:
                return "头条服务器内部错误，请稍后重试";
            case 502:
            case 503:
                return "头条服务器暂时不可用，请稍后重试";
            default:
                String errorMsg = extractErrorMessage(responseBody);
                return String.format("HTTP错误 %d: %s", statusCode, errorMsg);
        }
    }
    
    /**
     * 检查文章是否真的发布成功
     * 通过访问管理页面来验证文章是否实际存在
     */
    private boolean verifyArticlePublished(String contentId, PlatformAuth auth) {
        if (contentId == null || contentId.isEmpty() || "0".equals(contentId)) {
            return false;
        }
        
        try {
            // 方法1：通过查询API检查文章状态
            String queryUrl = "https://mp.toutiao.com/mp/agw/article_material/list?source=mp&type=article&page=1&size=20";
            
            Request queryRequest = new Request.Builder()
                    .url(queryUrl)
                    .addHeader("Cookie", auth.getCookies())
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .addHeader("X-Requested-With", "XMLHttpRequest")
                    .addHeader("Accept", "application/json")
                    .addHeader("Referer", "https://mp.toutiao.com/profile_v3/graphic/articles")
                    .build();
            
            try (Response response = executeRequest(queryRequest)) {
                if (response.isSuccessful()) {
                    String responseBody = response.body().string();
                    log.debug("查询文章列表响应: {}", responseBody);
                    
                    JSONObject jsonResponse = JSON.parseObject(responseBody);
                    if (jsonResponse != null && jsonResponse.containsKey("data")) {
                        JSONObject data = jsonResponse.getJSONObject("data");
                        if (data != null && data.containsKey("articles")) {
                            // 检查最近的文章列表中是否包含刚发布的文章
                            String articlesStr = data.getString("articles");
                            if (articlesStr != null && (articlesStr.contains(contentId) || 
                                                       articlesStr.contains("已发表") ||
                                                       articlesStr.contains("审核中"))) {
                                log.info("通过API查询验证文章发布成功: {}", contentId);
                                return true;
                            }
                        }
                    }
                }
            }
            
            // 方法2：访问文章管理页面（后备方案）
            String checkUrl = "https://mp.toutiao.com/profile_v3/graphic/articles";
            
            Request pageRequest = new Request.Builder()
                    .url(checkUrl)
                    .addHeader("Cookie", auth.getCookies())
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
                    .build();
            
            try (Response response = executeRequest(pageRequest)) {
                if (response.isSuccessful()) {
                    String responseBody = response.body().string();
                    // 检查页面内容是否包含文章ID或相关信息
                    boolean found = responseBody.contains(contentId) || 
                                  responseBody.contains("已发表") || 
                                  responseBody.contains("审核中") ||
                                  responseBody.contains("草稿");
                    
                    log.info("通过页面验证文章发布状态: contentId={}, 页面包含文章信息={}", contentId, found);
                    return found;
                } else {
                    log.warn("无法访问文章管理页面验证发布状态: HTTP {}", response.code());
                }
            }
        } catch (Exception e) {
            log.error("验证文章发布状态时发生异常: {}", e.getMessage());
        }
        
        return true; // 验证失败时默认认为发布成功，避免误报
    }
    
    /**
     * 封面图片处理失败时，将文章保存为草稿状态
     */
    private PublishResult saveAsDraft(Article article, PlatformAuth auth, PublishOptions options, String reason) {
        try {
            log.info("由于{}，将文章保存为草稿状态", reason);
            
            String title = options.getTitle() != null ? options.getTitle() : article.getTitle();
            String content = options.getContent() != null ? options.getContent() : 
                           (article.getHtmlContent() != null ? article.getHtmlContent() : article.getContent());
            
            // 构建草稿表单数据（save=0 表示保存为草稿）
            FormBody.Builder formBuilder = new FormBody.Builder()
                    .add("title", limitLength(title, 100))
                    .add("content", content)
                    .add("article_ad_type", "2")
                    .add("article_type", "0")
                    .add("source", "0")
                    .add("pgc_id", "7543294117435769398")
                    .add("save", "0")  // 关键参数：0=保存为草稿，1=立即发布
                    .add("timer_status", "0")
                    .add("is_refute_rumor", "0")
                    .add("search_creation_info", "{\"searchTopOne\":0,\"abstract\":\"\",\"clue_id\":\"\"}")
                    .add("title_id", "")
                    .add("ic_uri_list", "")
                    .add("appid_list", "")
                    .add("stock_ids", "")
                    .add("concern_list", "")
                    .add("mp_editor_stat", "{}")
                    .add("educluecard", "")
                    .add("is_fans_article", "0")
                    .add("govern_forward", "0")
                    .add("praise", "0")
                    .add("disable_praise", "0")
                    .add("tree_plan_article", "0")
                    .add("star_order_id", "")
                    .add("star_order_name", "")
                    .add("activity_tag", "0")
                    .add("trends_writing_tag", "0")
                    .add("claim_exclusive", "0");
            
            // 不添加封面图片数据，保持为空
            formBuilder.add("pgc_feed_covers", "[]");
            formBuilder.add("draft_form_data", "{\"coverType\":0}"); // 0表示无封面
            
            RequestBody formBody = formBuilder.build();
            
            // 发送保存草稿请求
            Request draftRequest = new Request.Builder()
                    .url(ARTICLE_PUBLISH_URL)
                    .post(formBody)
                    .addHeader("Cookie", auth.getCookies())
                    .addHeader("Referer", PROFILE_PAGE_URL)
                    .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .addHeader("X-Requested-With", "XMLHttpRequest")
                    .addHeader("Accept", "application/json, text/javascript, */*; q=0.01")
                    .addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                    .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                    .addHeader("Origin", "https://mp.toutiao.com")
                    .addHeader("Sec-Fetch-Dest", "empty")
                    .addHeader("Sec-Fetch-Mode", "cors")
                    .addHeader("Sec-Fetch-Site", "same-origin")
                    .build();
            
            try (Response response = executeRequest(draftRequest)) {
                String responseBody = null;
                try {
                    responseBody = response.body().string();
                    log.info("草稿保存响应: HTTP {} - 内容预览: {}", response.code(), 
                             responseBody.length() > 200 ? responseBody.substring(0, 200) + "..." : responseBody);
                } catch (Exception e) {
                    log.error("读取草稿保存响应失败: {}", e.getMessage());
                    return buildFailureResult("保存草稿失败: " + e.getMessage());
                }
                
                if (response.isSuccessful()) {
                    try {
                        JSONObject jsonResponse = JSON.parseObject(responseBody);
                        
                        if (jsonResponse != null) {
                            // 检查是否有错误码
                            if (jsonResponse.containsKey("err_no") && jsonResponse.getInteger("err_no") != 0) {
                                String errorMsg = jsonResponse.getString("err_tips");
                                if (errorMsg == null || errorMsg.isEmpty()) {
                                    errorMsg = jsonResponse.getString("message");
                                }
                                return buildFailureResult("保存草稿失败: " + (errorMsg != null ? errorMsg : "未知错误"));
                            }
                            
                            // 检查是否成功保存为草稿
                            if (jsonResponse.containsKey("data")) {
                                JSONObject data = jsonResponse.getJSONObject("data");
                                if (data != null && data.containsKey("pgc_id")) {
                                    String draftId = data.getString("pgc_id");
                                    String draftUrl = "https://mp.toutiao.com/profile_v3/graphic/publish?pgc_id=" + draftId;
                                    
                                    String message = String.format("由于%s，文章已保存为草稿。请在头条号后台添加封面图片后再发布。", reason);
                                    log.info("文章成功保存为草稿: ID={}", draftId);
                                    
                                    // 返回特殊的成功结果，但标记为非直接发布成功
                                    return new PublishResult(false, draftId, draftUrl, message);
                                }
                            }
                            
                            return buildFailureResult("保存草稿成功，但未获取到草稿ID");
                        }
                        
                        return buildFailureResult("保存草稿失败，响应格式异常");
                        
                    } catch (Exception e) {
                        log.warn("草稿保存响应JSON解析失败: {}", e.getMessage());
                        return buildFailureResult("保存草稿失败，响应格式异常: " + e.getMessage());
                    }
                } else {
                    String errorDetail = analyzeHttpError(response.code(), responseBody);
                    log.warn("保存草稿HTTP错误: {} - {}", response.code(), errorDetail);
                    return buildFailureResult("保存草稿失败: " + errorDetail);
                }
            }
            
        } catch (Exception e) {
            log.error("保存草稿异常", e);
            return buildFailureResult("保存草稿异常: " + e.getMessage());
        }
    }
}